import direct.directbase.DirectStart
from direct.actor import Actor
from direct.fsm import FSM
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task import Task
from direct.showbase.DirectObject import DirectObject
import math

environ = loader.loadModel("models/defaults/environment")
environ.reparentTo(render)

base.disableMouse()
base.camera.setPos(Point3(0, 200, 75))
base.camera.setHpr(0,-30,0)

class Rider (DirectObject):
    def __init__(self):
        
        self.actor = Actor.Actor("models/Animations/walking_anim", 
                         {"stand-walk":"models/Animations/stand2walkS",
                          "walk":"models/Animations/walking_anim", 
                          "runAT":"models/Animations/runningAT"})
    
        self.actor.setScale(.1,.1,.1)
        
        self.actor.reparentTo(render)
        self.actor.setPlayRate(.7, 'walk')
        self.stand2walkControl=self.actor.getAnimControl("stand-walk")
            
        self.mode="walk"
        
        self.keyMap = {"left":0, "right":0, "up":0, "down":0, "mouse-1":0, "mouse-3":0}

        
        self.accept("arrow_up", self.setKey, ["up", 1])
        self.accept("arrow_down", self.setKey, ["down", 1])
        self.accept("arrow_right", self.setKey, ["right", 1])
        self.accept("arrow_left", self.setKey, ["left", 1])
        self.accept("shift", self.setKey, ["shift", 1])
        self.accept("mouse1", self.setKey, ["mouse-1", 1])
        self.accept("mouse2", self.setKey, ["mouse-2", 1])
        self.accept("mouse3", self.setKey, ["mouse-3", 1])

        self.accept("enter", self.debug_pause)
        
        self.accept("arrow_up-up", self.setKey, ["up", 0])
        self.accept("arrow_down-up", self.setKey, ["down", 0])
        self.accept("arrow_right-up", self.setKey, ["right", 0])
        self.accept("arrow_left-up", self.setKey, ["left", 0])
        self.accept("mouse1-up", self.setKey, ["mouse-1", 0])
        self.accept("mouse2-up", self.setKey, ["mouse-2", 0])
        self.accept("mouse3-up", self.setKey, ["mouse-3", 0])
        
        self.step="R"
        self.state="stand"
        self.frame=0
        
        self.actor.pose("stand-walk", 0)
        
        self.speed=0/30
        
        self.prevMouseX=0
        self.prevMouseY=0

        #stats
        self.maxSpeed=90/30
        self.accelScale=1.0/210.0
        
        self.actor.pose("runAT", 1)
        taskMgr.add(self.RunAT, "running with ATs")

    def debug_pause(self):
        pass
    
    def setKey(self, key, value):
        self.keyMap[key] = value
#suggestions: put "stats" in __init__, apply everything to L2 and R2, seperate mouse H and R

    def RunAT(self, task):
        if self.keyMap["mouse-1"]!=0 and self.keyMap["mouse-3"]==0 and self.state=="stand":
            if self.step=="R":
                self.actor.setSx(self.actor, -1)
                self.step="L"
            self.actor.play("runAT", fromFrame=2, toFrame=41)
            self.frame=task.frame
            base.win.movePointer(0, base.win.getProperties().getXSize()/2, base.win.getProperties().getYSize()/2)
            self.prevMouseX=0
            self.prevMouseY=0
            
            self.speed=self.speed+(.5/30)
            self.state="stand-runL1"
        #add mouseP and adjust the pitch instead of speed
        elif self.state=="stand-runL1":
            self.mouseHR(30, 15, 1.0/60.0)
            self.speed=self.speed+(.5/30)
            if self.frame+39<=task.frame:
                self.state="runL1"
        if self.state=="runL1" and self.keyMap["mouse-1"]!=0:
            minSpeed=0/30
            offSet=10
            self.mouseHR(30, 15, 1.0/60.0)
            self.mouseP(45, 0, 45)
            
            if self.speed+(self.actor.getP()-offSet)*self.accelScale>=minSpeed and self.speed+(self.actor.getP()-offSet)*self.accelScale<=self.maxSpeed:#would be
                self.speed=self.speed+(self.actor.getP()-offSet)*self.accelScale
            elif self.speed+(self.actor.getP()-offSet)*self.accelScale<minSpeed:
                self.speed=minSpeed
            elif self.speed+(self.actor.getP()-offSet)*self.accelScale>self.maxSpeed:
                self.speed=self.maxSpeed
                
            if self.actor.getCurrentFrame("runAT")!=42:
                self.actor.pose("runAT", 42)
        if self.state=="runL1" and self.keyMap["mouse-1"]==0:
            self.actor.play("runAT", fromFrame=43, toFrame=74)
            self.frame=task.frame
            self.state="runL1-runL2"
        #adjust the pitch from where it is to a neural position (10 degrees?)
        if self.state=="runL1-runL2":
            if self.frame+31<=task.frame:
                self.state="runL2"                  
        if self.state=="runL2":
            minSpeed=0/30
            offSet=10
            self.mouseHR(30, 15, 1.0/60.0)
            if self.speed+(self.actor.getP()-offSet)*self.accelScale>=minSpeed and self.speed+(self.actor.getP()-offSet)*self.accelScale<=self.maxSpeed:#would be
                self.speed=self.speed+(self.actor.getP()-offSet)*self.accelScale
            elif self.speed+(self.actor.getP()-offSet)*self.accelScale<minSpeed:
                self.speed=minSpeed
            elif self.speed+(self.actor.getP()-offSet)*self.accelScale>self.maxSpeed:
                self.speed=self.maxSpeed
        '''
        #need new animation for leg switch
        
        if self.state=="runL2" and self.keyMap["mouse-3"]!=0:
            self.actor.play("runAT")            
            self.state="runL2-runR1"
        if self.state=="runL2-runR1":
            if self.frame+42<=task.frame:
            	self.state=runR1
        '''

            
        if self.keyMap["mouse-3"]!=0 and self.keyMap["mouse-1"]==0 and self.state=="stand":
            if self.step=="L":
                self.actor.setSx(self.actor, -1)
                self.step="R"
            self.actor.play("runAT", fromFrame=2, toFrame=41)
            self.frame=task.frame
            base.win.movePointer(0, base.win.getProperties().getXSize()/2, base.win.getProperties().getYSize()/2)
            self.prevMouseX=0
            self.prevMouseY=0                                                                                                                                                                                                                                                                                                                                        
            self.speed=self.speed+(.5/30)
            self.state="stand-runR1"
        elif self.state=="stand-runR1":
            self.mouseHR(30, 15, 1/60)
            self.speed=self.speed+(.5/30)
            if self.frame+39<=task.frame:
                self.state="runR1" 
        if self.state=="runR1" and self.keyMap["mouse-3"]!=0:
            minSpeed=0/30
            offSet=10
            self.mouseHR(30, 15, 1.0/60.0)
            self.mouseP(45, 0, 45)
            
            if self.speed+(self.actor.getP()-offSet)*self.accelScale>=minSpeed and self.speed+(self.actor.getP()-offSet)*self.accelScale<=self.maxSpeed:#would be
                self.speed=self.speed+(self.actor.getP()-offSet)*self.accelScale
            elif self.speed+(self.actor.getP()-offSet)*self.accelScale<minSpeed:
                self.speed=minSpeed
            elif self.speed+(self.actor.getP()-offSet)*self.accelScale>self.maxSpeed:
                self.speed=self.maxSpeed
                
            if self.actor.getCurrentFrame("runAT")!=42:
                self.actor.pose("runAT", 42)
        if self.state=="runR1" and self.keyMap["mouse-3"]==0:
            self.actor.play("runAT", fromFrame=43, toFrame=74)
            self.frame=task.frame
            self.state="runR1-runR2"
        if self.state=="runR1-runR2":
            if self.frame+31<=task.frame:
                self.state="runR2"                  
        if self.state=="runR2":
            pass
        '''
        #need new animation for leg switch
        
        if self.state=="runR2" and self.keyMap["mouse-1"]!=0:
            self.actor.play("runAT")            
            self.state="runR2-runL1"
        if self.state=="runR2-runL1":
            if self.frame+42<=task.frame:
                self.state=runL1
        '''
        
        base.camera.setPos(self.actor.getX()-(200*math.sin((self.actor.getH()*math.pi/180))),
                           self.actor.getY()+(200*math.cos((self.actor.getH()*math.pi/180))),
                           base.camera.getZ())
        base.camera.lookAt(self.actor)
        
        self.move()    
        return Task.cont
    
    def move(self):
        x=self.speed*math.sin((self.actor.getH()*math.pi/180))
        y=self.speed*math.cos((self.actor.getH()*math.pi/180))
        self.actor.setPos(self.actor.getX()+x, self.actor.getY()-y, self.actor.getZ())

    def mouseHR(self, limit, scale, scaleH):
        xBorder=.9
        if base.mouseWatcherNode.getMouseX()>xBorder:
            if (self.actor.getR()+(self.prevMouseX-xBorder)*scale)>=-limit:
                self.actor.setR(self.actor.getR()+(self.prevMouseX-xBorder)*scale)
            else:
                self.actor.setR(-limit)
            base.win.movePointer(0,
                                 base.win.getProperties().getXSize()*(1-xBorder)/2,
                                 base.win.getProperties().getYSize()*((-(base.mouseWatcherNode.getMouseY())+1)/2))
            self.prevMouseX=-xBorder
        elif base.mouseWatcherNode.getMouseX()<-xBorder:
            if (self.actor.getR()+(self.prevMouseX-(-xBorder))*scale)<=limit:
                self.actor.setR(self.actor.getR()+(self.prevMouseX-(-xBorder))*scale)
            else:
                self.actor.setR(limit)
            base.win.movePointer(0,
                                 base.win.getProperties().getXSize()*(1-((1-xBorder)/2)),
                                 base.win.getProperties().getYSize()*((-(base.mouseWatcherNode.getMouseY())+1)/2))            
            self.prevMouseX=xBorder
        elif self.prevMouseX!=base.mouseWatcherNode.getMouseX():
            if (self.actor.getR()+(self.prevMouseX-base.mouseWatcherNode.getMouseX())*scale)>=-limit and (self.actor.getR()+(self.prevMouseX-base.mouseWatcherNode.getMouseX())*scale)<=limit:
                self.actor.setR(self.actor.getR()+(self.prevMouseX-base.mouseWatcherNode.getMouseX())*scale)
            elif (self.actor.getR()+(self.prevMouseX-base.mouseWatcherNode.getMouseX())*scale)<-limit:
                self.actor.setR(-limit)
            elif (self.actor.getR()+(self.prevMouseX-base.mouseWatcherNode.getMouseX())*scale)>limit:
                self.actor.setR(limit)
            self.prevMouseX=base.mouseWatcherNode.getMouseX()
        self.actor.setH(self.actor.getH()+(self.actor.getR()*scaleH))#seperate
            
    def mouseP(self, limit, limitBack, scale):
        yBorder=.9
        if base.mouseWatcherNode.getMouseY()>yBorder:
            if (self.actor.getP()+(yBorder-self.prevMouseY)*scale)<=limit:
                self.actor.setP(self.actor.getP()+(yBorder-self.prevMouseY)*scale)
            else:
                self.actor.setP(limit)
            base.win.movePointer(0,
                                 base.win.getProperties().getXSize()*((base.mouseWatcherNode.getMouseX()+1)/2),
                                 base.win.getProperties().getYSize()*(1-((1-yBorder)/2)))
            self.prevMouseY=-yBorder
        elif base.mouseWatcherNode.getMouseY()<-yBorder:
            if (self.actor.getP()+(-yBorder-self.prevMouseY)*scale)>=limitBack:
                self.actor.setP(self.actor.getP()+(-yBorder-self.prevMouseY)*scale)
            else:
                self.actor.setP(limitBack)
            base.win.movePointer(0,
                                 base.win.getProperties().getXSize()*((base.mouseWatcherNode.getMouseX()+1)/2),
                                 base.win.getProperties().getYSize()*(1-yBorder)/2)
            self.prevMouseY=yBorder  
        elif self.prevMouseY!=base.mouseWatcherNode.getMouseY():
            if (self.actor.getP()+(base.mouseWatcherNode.getMouseY()-self.prevMouseY)*scale)<=limit and (self.actor.getP()+(base.mouseWatcherNode.getMouseY()-self.prevMouseY)*scale)>=limitBack:
                self.actor.setP(self.actor.getP()+(base.mouseWatcherNode.getMouseY()-self.prevMouseY)*scale)
            elif (self.actor.getP()+(base.mouseWatcherNode.getMouseY()-self.prevMouseY)*scale)>limit:
                self.actor.setP(limit)
            elif (self.actor.getP()+(base.mouseWatcherNode.getMouseY()-self.prevMouseY)*scale)<limitBack:
                self.actor.setP(limitBack)
            self.prevMouseY=base.mouseWatcherNode.getMouseY()        

 
Rider()

run()
